#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import re
from datetime import datetime
from typing import Dict, List, Set, Optional, Tuple
from enum import Enum
import logging
from tree_sitter import Tree, Node
# 导入数据结构
from parser.refactor.data_structures import (
    ClassInfo, ParserContext, DependencyContext, DependencyType,
    MethodInfo, FieldInfo, AnnotationInfo, GraphNodeInfo, GraphEdgeInfo,
    MetadataInfo, RelationshipInfo, RelationshipCollection,
    ClassType, Visibility, FileInfo, ParameterInfo, CommentInfo
)
from parser.refactor.java_metadata_extractor.java_metadata_extractor import JavaMetadataExtractor
from parser.refactor.java_node_type import (JavaNodeType)

logger = logging.getLogger(__name__)


class JavaAnnotationExtractor(JavaMetadataExtractor):
    """Java注解元数据提取器"""

    def extract_annotation_info(self, node: Node, code_bytes: bytes, package_name: str = "") -> Optional[
        AnnotationInfo]:
        """
        从注解声明节点提取注解信息

        Args:
            node: 注解声明节点
            code_bytes: 源代码字节
            package_name: 包名

        Returns:
            Optional[AnnotationInfo]: 注解信息对象，如果解析失败则返回None
        """
        try:
            # 1. 提取注解名称
            annotation_name = None
            for child in node.children:
                if child.type == JavaNodeType.IDENTIFIER:
                    annotation_name = self.get_node_text(child, code_bytes)
                    break

            if not annotation_name:
                logger.error("无法获取注解名称")
                return None

            # 2. 构建全限定名
            full_name = f"{package_name}.{annotation_name}" if package_name else annotation_name

            # 3. 初始化注解信息
            annotation_info = AnnotationInfo(
                name=annotation_name,
                full_name=full_name,
                target=[],  # 初始为空，后续根据元注解确定
                parameters={}
            )

            # 4. 提取注解参数定义
            self._extract_annotation_parameters(node, code_bytes, annotation_info.parameters)

            # 5. 提取注解目标（从@Target元注解）
            self._extract_annotation_target(node, code_bytes, annotation_info)

            return annotation_info

        except Exception as e:
            logger.error(f"提取注解信息时出错: {str(e)}")
            return None


    def _extract_annotation_parameters(self, node: Node, code_bytes: bytes, parameters: Dict[str, any]):
        """
        提取注解参数定义

        Args:
            node: 注解声明节点
            code_bytes: 源代码字节
            parameters: 存储参数的字典
        """
        # 查找注解类型体
        for child in node.children:
            if child.type == JavaNodeType.ANNOTATION_TYPE_BODY:
                # 遍历所有参数声明
                for element in child.children:
                    if element.type == JavaNodeType.ANNOTATION_TYPE_ELEMENT_DECLARATION:
                        param_info = self._parse_parameter_declaration(element, code_bytes)
                        if param_info:
                            name, value = param_info
                            parameters[name] = value

    def _parse_parameter_declaration(self, node: Node, code_bytes: bytes) -> Optional[tuple]:
        """
        解析参数声明

        Args:
            node: 参数声明节点
            code_bytes: 源代码字节

        Returns:
            Optional[tuple]: (参数名, 参数信息)元组，解析失败返回None
        """
        try:
            param_name = None
            param_type = None
            default_value = None

            for child in node.children:
                # 获取参数名
                if child.type == JavaNodeType.IDENTIFIER:
                    param_name = self.get_node_text(child, code_bytes)

                # 获取参数类型
                elif child.type in [JavaNodeType.TYPE_IDENTIFIER, JavaNodeType.ARRAY_TYPE] or JavaNodeType.is_base_parameter_type(child.type):
                    param_type = self.get_node_text(child, code_bytes)

                # 获取默认值
                elif child.type == JavaNodeType.DEFAULT:
                    value_node = child.next_sibling
                    if value_node.type == "string_literal":
                        # 去掉引号
                        default_value = code_bytes[value_node.start_byte + 1:value_node.end_byte - 1].decode('utf-8')
                    elif value_node.type == "true" or value_node.type == "false":
                        default_value = value_node.type == "true"
                    elif value_node.type == "decimal_integer_literal":
                        default_value = int(code_bytes[value_node.start_byte:value_node.end_byte].decode('utf-8'))

            if param_name and param_type:
                return param_name, {
                    'type': param_type,
                    'default_value': default_value,
                    'required': default_value is None
                }

            return None

        except Exception as e:
            logger.error(f"解析参数声明时出错: {str(e)}")
            return None

    def _extract_annotation_target(self, node: Node, code_bytes: bytes, annotation_info: AnnotationInfo):
        """
        从@Target元注解提取注解目标

        Args:
            node: 注解声明节点
            code_bytes: 源代码字节
            annotation_info: 注解信息对象
        """
        # 查找@Target元注解
        for child in node.children:
            if child.type == JavaNodeType.MODIFIERS:
                for modifier in child.children:
                    if modifier.type == JavaNodeType.ANNOTATION:
                        annotation_name = None
                        for anno_child in modifier.children:
                            if anno_child.type == JavaNodeType.IDENTIFIER:
                                annotation_name = self.get_node_text(anno_child, code_bytes)

                        if annotation_name == 'Target':
                            # 解析@Target的值
                            annotation_info.target = self._parse_target_value(modifier, code_bytes)


    def _parse_target_value(self, target_node: Node, code_bytes: bytes) -> list:
        """
        解析@Target注解的值

        Args:
            target_node: @Target注解节点
            code_bytes: 源代码字节

        Returns:
            list: 目标类型列表
        """
        targets = []

        # 映射ElementType枚举值到目标类型字符串
        target_mapping = {
            'TYPE': 'class',
            'FIELD': 'field',
            'METHOD': 'method',
            'PARAMETER': 'parameter',
            'CONSTRUCTOR': 'constructor',
            'LOCAL_VARIABLE': 'local_variable',
            'ANNOTATION_TYPE': 'annotation_type',
            'PACKAGE': 'package'
        }

        try:
            for child in target_node.children:
                if child.type == JavaNodeType.ANNOTATION_ARGUMENT_LIST:
                    for arg in child.children:
                        if arg.type == JavaNodeType.FIELD_ACCESS:
                            element_type = self.get_node_text(arg, code_bytes)
                            if '.' in element_type:
                                element_type = element_type.split('.')[-1]
                            if element_type in target_mapping:
                                targets.append(target_mapping[element_type])
        except Exception as e:
            logger.error(f"解析@Target值时出错: {str(e)}")

        return targets

